<?php
# stub to access names of sources the handler should be listening to
class Test_Event_Handler_Stub_SourceAccessor extends Event_Handler {
	public function getSources(){
		return $this->asHandlerFor;
	}
	# used in conjunction with eventtriggerer class below
	protected function onNew(){
		throw new Exception('triggered on new', 2);
	}
	# used in conjunction with eventtriggerer class below
	protected function onStatic(){
		throw new Exception('triggered on static', 3);
	}
	public function getEventHandle(Event_Event $oEvent){
		return parent::getEventHandle($oEvent);
	}
}
# event source used to test whether handler listens to proper source
class Test_Event_Handler_Stub_EventTriggerer {
	public static function trigger(){
		new Event_Event('static');
	}
	public function __construct(){
		new Event_Event('new');
	}
}

class Test_Event_Handler extends PHPUnit_Framework_TestCase {
	/**
	 * Expected behaviour: handlers respond only to events triggered by sources the listen to
	 * Test setup:
	 * use the Test_Event_Handler_Stub_EventTriggerer which triggers a "new" event on construction
	 * + create handler to listen not to Test_Event_Handler_Stub_EventTriggerer and make sure it doesnot handle
	 * + create handler to listen to Test_Event_Handler_Stub_EventTriggerer and make sure it does handle
	 */
	public function test_handler_listens_to_proper_sources(){
		new Test_Event_Handler_Stub_SourceAccessor(__CLASS__);
		new Test_Event_Handler_Stub_EventTriggerer();
		
		new Test_Event_Handler_Stub_SourceAccessor('Test_Event_Handler_Stub_EventTriggerer');
		try {
			new Test_Event_Handler_Stub_EventTriggerer();
			$this->fail('Handler has not responded to event should have thrown an exception');
		}
		catch (Exception $oEx){
			if (false === ($oEx->getCode() === 2 && $oEx->getMessage() === 'triggered on new')){
				$this->fail('improper exception received');
			}
		}
		try {
			Test_Event_Handler_Stub_EventTriggerer::trigger();
			$this->fail('Statically triggered event not handled');
		}
		catch (Exception $oEx) {
			if (false === ($oEx->getCode() === 3 && $oEx->getMessage() === 'triggered on static')){
				$this->fail('improper exception received');
			}
		}
	}
	
	/**
	 * Expected behaviour: Constructing a handler with names of types to listed to will have it
	 * register these names
	 *
	 * Test setup: construct with:
	 * + no names (should throw an error, missing arg 1)
	 * + one name
	 * + more names
	 */
	public function test_setup_handler_to_listen_to_sources(){ // __construct
		# 1 source
		$oStub = new Test_Event_Handler_Stub_SourceAccessor('Source one');
		$this->assertEquals(array('Source one'), $oStub->getSources(), 'One source given, yet not not registered');
		# > 1 source
		$oStub = new Test_Event_Handler_Stub_SourceAccessor('Source one', 's2', 's3');
		$this->assertEquals(array('Source one', 's2', 's3'), $oStub->getSources(), 'Three sources given, yet not not registered');
		
		# no source
		try { # expect "missing argument 1"
			new Test_Event_Handler_Stub_SourceAccessor();
			$this->fail('No sources given, yet no error');
		} catch (PHPUnit_Framework_Error $oErr){}
	}
	
	public function test_handler_listens_on_static_calls(){
	}
	
	/**
	 * Events have a handle that corresponds to their name, e.g. before-create becomes onBeforeCreate
	 *
	 * Expected behaviour: types should be converted from [a-z0-9]+(-[a-z0-9]+)* to on[A-Z0-9][a-z0-9]*([A-Z0-9][a-z0-9]*)*
	 * i.e.: camelcased based on "-"-separator and prefixed with "on"
	 * 
	 * Test setup:
	 * create events with different types of type:
	 * + multiple "-" all lowercase
	 * + multiple "-" some camelcased
	 * + no "-", all lowercase
	 * + no "-", camelcase
	 */
	public function test_event_name_corresponds_properly_to_handle(){ // getHandle
		$asPossibleType = array( 
			'multiple-type-type' => 'onMultipleTypeType',
			'multiple-tyPe-Type' => 'onMultipleTyPeType',
			'singletype' => 'onSingletype',
			'singleType' => 'onSingleType'
		);
		$oHandler = new Test_Event_Handler_Stub_SourceAccessor('non existing classname');
		foreach ($asPossibleType as $sPossibleType => $sExpectedHandle){
			$oEvent = new Event_Event($sPossibleType);
			$this->assertEquals($sExpectedHandle, $oHandler->getEventHandle($oEvent), 'event handle does not match type ('.$sPossibleType.', '.$sExpectedHandle.')');
		}
	}
	
	/**
	 * A handler may not need to handle ALL events dispatched by a source. This method will 
	 * make sure that nothing crashes when an event is not handled, e.g. when new events are
	 * added to the source or events just not need to be handled in the first place. 
	 *  
	 * @param String $sHandle
	 * @param array $amArgv
	 */
	public function test_unhandled_event_types_do_nothing(){
		# how to test these things?
		$oEventHandler = new Test_Event_Handler_Stub_SourceAccessor(__CLASS__);
		new Event_Event('unhandled');
	}
}